package org.example.judge.controller;

import lombok.extern.slf4j.Slf4j;
import org.example.judge.oj.JudgeResult;
import org.example.judge.service.SubmitService;
import org.example.judge_common.properties.JudgeProperties;
import org.example.judge.service.ProblemService;
import org.example.judge_common.annotation.AuthAnnotation;
import org.example.judge_common.entity.PageResult;
import org.example.judge_common.entity.RequestProblemParams;
import org.example.judge_common.entity.ResponseResult;
import org.example.judge_common.hander.RetrunMsgException;
import org.example.judge_common.util.IdWorker;
import org.example.judge_common.util.MyUtils;
import org.example.judge_pojo.Auth;
import org.example.judge_pojo.Problem;
import org.example.judge_pojo.Tag;
import org.example.judge_pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.imageio.stream.FileImageInputStream;
import javax.imageio.stream.ImageInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;

@CrossOrigin
@Controller
@RequestMapping("/problem")
@Slf4j
public class ProblemController {

    @Qualifier("ProblemServiceImpl")
    @Autowired
    private ProblemService problemService;

    @Qualifier("SubmitServiceImpl")
    @Autowired
    private SubmitService submitService;
    @Autowired
    private IdWorker idWorker;

    @Autowired
    private JudgeProperties judgeProperties;





    @PostMapping("/search")
    @ResponseBody
    @AuthAnnotation(value = "problem_search",exist = false)
    public ResponseResult search(RequestProblemParams params,HttpServletRequest request){
        if(params==null)params = new RequestProblemParams();
        User loginUser = (User) request.getAttribute("loginUser");
        if(!Auth.isAdmin(loginUser))params.setAuth(0); //不能查看私密题目
        if(loginUser!=null)params.setUserId(loginUser.getId());
        PageResult<Problem> res = problemService.search(params);
        if(res.getTotal()==0)return ResponseResult.NotData();
        return ResponseResult.success().setData(res);
    }

    /**
     * 上传文件文件
     * @param file
     * @param request
     * @return 返回生成的文件file_id + 后缀名
     * @throws RetrunMsgException
     */
    @PostMapping("/upload")
    @ResponseBody
    @AuthAnnotation({Auth.ADMINISTRATOR})
    public ResponseResult upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws RetrunMsgException {
        if(file==null)return ResponseResult.fail("文件上传不符合要求");
        File dir = new File(judgeProperties.getDataDir(), "problem");
        if(!dir.exists())dir.mkdirs();
        String id = idWorker.nextId().toString();
        int i = Objects.requireNonNull(file.getOriginalFilename()).lastIndexOf(".");
        if(i==-1)return ResponseResult.fail("文件上传不符合要求");
        String type = file.getOriginalFilename().substring(i); //获取文件后缀名
        try {

            file.transferTo(new File(dir,id+type));
        } catch (IOException e) {
            e.printStackTrace();
            throw new RetrunMsgException("文件保存失败");
        }
        return ResponseResult.success().setData(id+type);
    }
    @RequestMapping("/download/{id}")
    @AuthAnnotation({Auth.CLIENT})
    public void down(@PathVariable("id") String id, HttpServletResponse response) throws  IOException {
        File dir = new File(judgeProperties.getDataDir(), "problem");
        String filename = id;
        //文件所在位置
        File file = new File(dir , filename);
        ServletOutputStream outputStream = null;
        FileInputStream fileInputStream = null;

//        response.setHeader("content-type", "video/mp4");
        try{

            outputStream = response.getOutputStream();
            fileInputStream = new FileInputStream(file);
            byte[] bytes = new byte[1024];
            int read = 0;
            while ((read = fileInputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, read);
            }
        } catch (Exception e) {
            log.error("文件" + filename + "读取失败: " + e.getMessage());
//            throw new RetrunMsgException("系统找不到指定文件");
            outputStream.write("系统找不到指定文件".getBytes("GBK"));
        } finally {
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    log.error("文件" + filename + "输出流关闭失败: " + e.getMessage());
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    log.error("response.outputStream输出流关闭失败: " + e.getMessage());
                }
            }

        }
    }
    @PostMapping(value = "/save",name = "PROBLEM_SAVE")
    @AuthAnnotation({"problem_save", Auth.ADMINISTRATOR})
    @ResponseBody
    public ResponseResult save(@RequestBody Problem problem, HttpServletRequest request){
        User loginUser = (User) request.getAttribute("loginUser");
        problem.setUpdateUser(loginUser.getUsername());
        boolean save = problemService.save(problem);
        if(!save)return ResponseResult.fail("题目上传失败");
        return ResponseResult.success();
    }

    @PostMapping("/detail/{id}")
    @AuthAnnotation({"problem_select", Auth.CLIENT})
    @ResponseBody
    public ResponseResult selectById(@PathVariable String id,HttpServletRequest request,String resp){
        Problem byId = problemService.getById(id);
        if(byId==null)return ResponseResult.NotData();
        if("title".equals(resp)){  //只返回名字
            return ResponseResult.success().setData(byId.getTitle());
        }
        User loginUser = (User) request.getAttribute("loginUser");
        //表示属于远程调用
        if(loginUser==null)return ResponseResult.success().setData(byId);
        if(byId.getAuth()!=0){  //非开放性试题

            if(!Auth.isAdmin(loginUser))return ResponseResult.unAuditor(); //无访问权限
        }
        //是否提交过

        //通过
        if (submitService.getSumbitSum(byId.getId(),loginUser.getId(), JudgeResult.ACCEPTED)>0) {
            byId.setStatus(0);
        }else if(submitService.getSumbitSum(byId.getId(),loginUser.getId(),null)>0){
            //未通过
            byId.setStatus(1);
        }



        return ResponseResult.success().setData(byId);
    }
    @PutMapping("/update")
    @AuthAnnotation({"problem_update", Auth.ADMINISTRATOR})
    @ResponseBody
    public ResponseResult updateById(@RequestBody Problem problem){
        problemService.updateById(problem);
        return ResponseResult.success();
    }

    @DeleteMapping("/delete/{id}")
    @AuthAnnotation({"problem_delete", Auth.ADMINISTRATOR})
    @ResponseBody
    @Transactional
    public ResponseResult deleteById(@PathVariable String id,HttpServletRequest request){


        //删除上传的文件
        Problem byId = problemService.getById(id);
        if(byId==null)return ResponseResult.fail("不存在该题目");
        if(byId.getType()==1){  //需删除上传的文件
            File problem = new File(judgeProperties.getDataDir(), "problem");
            new File(problem,byId.getFileId()).deleteOnExit();
        }
        problemService.removeById(id); //删除题目
        User loginUser = (User) request.getAttribute("loginUser");
        log.info("用户{}删除了题目ID：{}",loginUser.getUsername(),id);
        return ResponseResult.success();
    }



}
